//*************************************************************************************
//* 作    者： zouhunter
//* 创建时间： 2021-09-17 07:10:36
//* 描    述： 蝴蝶分组移动

//* ************************************************************************************
using System.Collections;
using UnityEngine;
using UFrame.State;
using UFrame.Tween;

public class Butteryflys : MonoBehaviour, ITween
{
    [SerializeField]
    protected float m_range;
    [SerializeField]
    protected Transform[] m_elements;
    [SerializeField]
    protected Bounds m_bounds;
    [SerializeField]
    protected float m_flySpeed = 0.1f;
    [SerializeField]
    protected float m_rotateSpeed = 10;
    [SerializeField]
    protected float m_verticalAngle = 30;
    [SerializeField]
    protected float m_changeTime = 3;
    //protected Vector3 m_centerPos;
    protected EventStateCtrl<State> m_stateCtrl;
    protected State m_state;
    protected Transform m_flyCenter;

    public bool IsPlaying { get; protected set; }
    public bool Valid => isActiveAndEnabled;
    public bool Enabled => enabled;
    public enum State
    {
        None,
        Idle,
        Move,
        Turning
    }
    protected Vector3 m_targetPos;
    protected Vector3 m_moveDirection;
    protected float m_xOffset;
    protected float m_hightSize;
    protected float m_idleTimer;
    protected float m_distanceOffset;
    protected bool m_moveOut;
    protected float m_changeTimer;
    protected Vector3 m_turnDirection;
    protected Vector3 m_startDirection;

    IEnumerator Start()
    {
        //m_stateCtrl = new EventStateCtrl<State>();
        //m_stateCtrl.SetUpdateEvent(State.Idle, OnIdle);
        //m_stateCtrl.SetUpdateEvent(State.Move, OnMoveForward);
        //m_stateCtrl.SetUpdateEvent(State.Turning, OnRotate);
        m_flyCenter = new GameObject("group").GetComponent<Transform>();
        m_flyCenter.transform.SetParent(transform);
        m_moveDirection = m_flyCenter.forward;
        if (m_elements.Length > 0)
        {
            m_flyCenter.transform.position = m_elements[0].position;
            for (int i = 0; i < m_elements.Length; i++)
            {
                m_elements[i].SetParent(m_flyCenter);
                yield return new WaitForSeconds(0.3f);
                var anim = m_elements[i].GetComponentInChildren<Animation>();
                if(anim)
                    anim.Play();
            }
            IsPlaying = true;
            m_state = State.Idle;
        }
    }

    private void OnEnable()
    {
        TweenAgent.Instance.StartTween(this);
    }

    private void OnDisable()
    {
        TweenAgent.Instance.StopTween(this);
    }

    public void Refresh()
    {
        m_stateCtrl.UpdateState(m_state);
    }

    public void EnableTween()
    {
        gameObject.SetActive(true);
    }

    public void DisableTween()
    {
        gameObject.SetActive(false);
    }

    private void OnDrawGizmos()
    {
        Gizmos.DrawWireCube(m_bounds.center + transform.position, m_bounds.size);
    }

    private void RefreshFlyCenter()
    {
        var localEuler = m_flyCenter.localEulerAngles;
        localEuler.y += m_rotateSpeed * Time.deltaTime;
        m_xOffset += m_rotateSpeed * Time.deltaTime * Mathf.Deg2Rad;
        localEuler.x = Mathf.Sin(m_xOffset) * m_verticalAngle;
        m_flyCenter.localEulerAngles = localEuler;
    }

    private State OnIdle(State state)
    {
        if(Time.time - m_idleTimer < 0.5f)
            return state;

        var randomX = Random.Range(m_bounds.min.x + m_range, m_bounds.max.x -  m_range);
        var randomY = Random.Range(m_bounds.min.y + m_range, m_bounds.max.y -  m_range);
        var randomZ = Random.Range(m_bounds.min.z + m_range, m_bounds.max.z - m_range);
        m_targetPos = new Vector3(randomX, randomY, randomZ);
        m_targetPos = transform.TransformPoint(m_targetPos);
        m_changeTimer = Time.time;
        m_startDirection = m_moveDirection;
        return State.Move;
    }

    private State OnMoveForward(State state)
    {
        var retio = (Time.time - m_changeTimer) / m_changeTime;
        if (retio > 1)
        {
            return State.Idle;
        }

        if(Physics.Raycast(m_flyCenter.position, m_moveDirection, out var hit, m_range * 3))
        {
            //m_hightSize = hit.collider.bounds.size.magnitude;
            m_changeTimer = Time.time;
            m_startDirection = m_moveDirection;
            m_turnDirection = -m_moveDirection;
            return State.Turning;
        }

        if(retio < 0.25f)
            m_moveDirection = Vector3.Lerp(m_startDirection, m_targetPos - m_flyCenter.position, retio * 4);

        m_flyCenter.transform.position += m_moveDirection * m_flySpeed * Time.deltaTime;
        RefreshFlyCenter();
        RefreshElement();
        return state;
    }
    private State OnRotate(State state)
    {
        var retio = (Time.time - m_changeTimer) / m_changeTime;
        if (retio > 1)
            return State.Idle;
        m_moveDirection = Vector3.Lerp(m_startDirection, m_turnDirection, retio);
        m_flyCenter.transform.position += m_moveDirection * m_flySpeed * Time.deltaTime;
        return state;
    }

    private void RefreshElement()
    {
        if (m_elements == null || m_elements.Length < 1)
            return;
        if(m_moveOut)
        {
            m_distanceOffset += Time.deltaTime * 0.01f;
            if(m_distanceOffset > m_range * 0.3f)
                m_moveOut = false;
        }
        else
        {
            m_distanceOffset -= Time.deltaTime * 0.01f;
            if (m_distanceOffset < -m_range * 0.3f)
                m_moveOut = true;
        }
        var angle = 360 / m_elements.Length;
        for (int i = 0; i < m_elements.Length; i++)
        {
            var element = m_elements[i];
            element.localPosition = Quaternion.AngleAxis(angle * i, Vector3.up) * Vector3.forward * (m_range + m_distanceOffset);
            element.forward = m_moveDirection;
        }
    }
}
